package com.sinodata.bsm.cicp.collector.aix;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.log4j.Logger;

import com.sinodata.bsm.cicp.collector.Collector;
import com.sinodata.bsm.cicp.exception.CollectorException;
import com.sinodata.bsm.cicp.util.CommandReader;
import com.sinodata.bsm.common.constants.DataTypeConstants;
import com.sinodata.bsm.common.vo.ResPropertyValue;

/**
 * 
 * <p>
 * Description: AIX errpt采集器
 * 
 * errpt timestamp格式是：MMddHHmmYY
 * 
 * 参数说明：cycle是errpt压缩的时间
 * </p>
 *
 * @author wangpeng
 * @version 1.0

 * <p>
 * History: 
 *
 * Date                     Author         Version     Description
 * ---------------------------------------------------------------------------------
 * 2012-10-25 下午06:33:22          wangpeng        1.0         To create
 * </p>
 *
 * @since 
 * @see
 */
public class AixErrpt extends Collector {

    private static final Logger logger = Logger.getLogger("AixErrpt");
    private static final String strMatch = "(\\S+)\\s+(\\d{10})\\s+(\\S+)\\s+(\\w)\\s+(\\S+)\\s+(.*)";
    private static final Pattern descriptionPattern = Pattern.compile("\\S+\\s*:\\s*(.*)");

    private static final Map<String, Long> deviceMap = new HashMap<String, Long>();
    private long cycleSecond = 3 * 24 * 60 * 60 * 1000;

    @Override
    public List<ResPropertyValue> collect(String ip) throws CollectorException {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String nowtime = sdf.format(new Date());
        String cycle = this.getParamMap().get("cycle");
        if (cycle != null && cycle.matches("\\d+")) {
            cycleSecond = Integer.valueOf(cycle) * 60 * 1000;
        }
        String[] descriptionColumnsEN = this.getDescriptionColumsEN();
        String[] descriptionColumnsZH = this.getDescriptionColumsZH();
        List<ResPropertyValue> values = new ArrayList<ResPropertyValue>();
        ResPropertyValue propertyValueX = null;
        ResPropertyValue.PropValue[] propValues = null;
        String lastDateStr = null;
        String cmd = null;
        BufferedReader reader = null;
        String[] propMetas = getPropMeta();
        String timeStamp = null;
        Set<String> identifierList = new LinkedHashSet<String>();
        boolean flag = true;
        try {
            lastDateStr = this.getErrptDate(ip);
            logger.info(nowtime + ";ip[" + ip + "];lastDateStr[" + lastDateStr + "]");
            timeStamp = lastDateStr;
            if (lastDateStr != null) {
                cmd = "errpt -s " + formateErrptDate(lastDateStr, 60 * 1000L);
                logger.info(nowtime + ";ip[" + ip + "];cmd[" + cmd + "]");
                reader = CommandReader.getReader(ip, cmd, 0, 0);
                String strLine = null;
                Pattern pattern = Pattern.compile(strMatch);
                while ((strLine = reader.readLine()) != null) {
                    Matcher matcher = pattern.matcher(strLine);
                    if (matcher.find()) {
                        logger.info(nowtime + ";ip[" + ip + "];strLine1[" + strLine + "]");
                        String type = matcher.group(3);
                        String cls = matcher.group(4);
                        if (!type.equals("P") && !cls.equals("H")) {
                            continue;
                        }

                        String identify = matcher.group(1);
                        String resname = matcher.group(5);
                        String key = identify + " -N " + resname;
                        if (identifierList.contains(key)) {
                            continue;
                        }
                        if (isRepeat(ip + "_" + key)) {
                            continue;
                        }
                        logger.info(nowtime + ";ip[" + ip + "];strLine2[" + strLine + "]");
                        identifierList.add(key);
                        propertyValueX = new ResPropertyValue();
                        propValues = new ResPropertyValue.PropValue[9];
                        for (int i = 0; i < 5; i++) {
                            propValues[i] = ResPropertyValue.createPropValue(matcher.group(i + 1), propMetas[i]);
                        }
                        propValues[6] = ResPropertyValue.createPropValue(DataTypeConstants.BOOLEAN_VALUE_FALSE, propMetas[6]);
                        propertyValueX.setValues(propValues);
                        values.add(propertyValueX);
                        if (flag) {
                            flag = false;
                            timeStamp = matcher.group(2);
                        }
                    }
                }
                if (identifierList.size() > 0) {
                    StringBuffer buffer = new StringBuffer();
                    for (String e : identifierList) {
                        logger.info(nowtime + ";ip[" + ip + "];identifierList[" + e + "]");
                        buffer.append("errpt -aj ");
                        buffer.append(e);
                        buffer.append(" |head -n 15;");
                    }
                    logger.info(nowtime + ";ip[" + ip + "];buffer[" + buffer.toString() + "]");
                    reader = CommandReader.getReader(ip, buffer.toString(), 0, 0);
                    int i = 0;
                    while ((strLine = reader.readLine()) != null) {
                        logger.info(nowtime + ";ip[" + ip + "];strLine3[" + strLine + "]");
                        strLine = strLine.trim();
                        StringBuffer sb = null;
                        if (strLine.startsWith("LABEL")) {//表示一个新的errpt开始
                            ResPropertyValue.PropValue[] propValue = values.get(i++).getValues();
                            sb = new StringBuffer("<br>");
                            for (int j = 0; j < descriptionColumnsEN.length; j++) {
                                String e = descriptionColumnsEN[j];
                                Matcher matcher = descriptionPattern.matcher(strLine);
                                if (strLine.startsWith(e) && matcher.find()) {
                                    sb.append(descriptionColumnsZH[j]);
                                    sb.append("\t:\t");
                                    sb.append(matcher.group(1));
                                    sb.append("<br>");
                                    strLine = reader.readLine();
                                    if (j == 0) {
                                        propValue[7] = ResPropertyValue.createPropValue(matcher.group(1), propMetas[7]);
                                    } else if (j == 11) {
                                        propValue[8] = ResPropertyValue.createPropValue(matcher.group(1), propMetas[8]);
                                    }
                                } else {
                                    sb.append(descriptionColumnsZH[j]);
                                    sb.append("\t:");
                                    sb.append("<br>");
                                    if (j == 0) {
                                        propValue[7] = ResPropertyValue.createPropValue("", propMetas[7]);
                                    } else if (j == 11) {
                                        propValue[8] = ResPropertyValue.createPropValue("", propMetas[8]);
                                    }
                                }
                                if (strLine == null) {
                                    break;
                                }
                                strLine = strLine.trim();
                            }
                            propValue[5] = ResPropertyValue.createPropValue(sb.toString(), propMetas[5]);
                        }
                    }
                }
            } else {
                cmd = "errpt |head -2|awk 'NR>1 {print $2}'";
                reader = CommandReader.getReader(ip, cmd, 0, 0);
                if (reader != null) {
                    String tmp = null;
                    while ((tmp = reader.readLine()) != null && tmp.trim().matches("\\d{10}")) {
                        timeStamp = tmp.trim();
                    }
                }
                if (timeStamp == null || !timeStamp.matches("\\d{10}")) {
                    return null;
                }
            }
            this.saveErrptDate(ip, timeStamp);

        } catch (Exception e) {
            logger.error("error execute errpt ip" + ip, e);
            // throw new CollectorException(e);
        } finally {
            IOUtils.closeQuietly(reader);
        }
        if (values != null && values.size() > 0) {
            for (ResPropertyValue e : values) {
                ResPropertyValue.PropValue[] propValue = e.getValues();
                logger.info(nowtime + ";ip[" + ip + "];" + propValue.toString());
            }
        }
        return values;
    }

    private String getErrptDate(String ip) throws IOException {
        String fileName = "save/" + ip + "_ERRPT.od";
        File file = new File(fileName);
        if (!file.exists()) {
            return null;
        }
        return FileUtils.readFileToString(file);
    }

    private void saveErrptDate(String ip, String date) throws IOException {
        File saveDir = new File("save");
        if (!saveDir.exists()) {
            saveDir.mkdir();
        }
        String fileName = "save/" + ip + "_ERRPT.od";
        File file = new File(fileName);
        if (!file.exists()) {
            try {
                file.createNewFile();
            } catch (IOException e) {
                logger.error("failed to create new file", e);
            }
        }
        FileUtils.writeStringToFile(file, date);
    }

    private String formateErrptDate(String date, long add) throws ParseException {
        SimpleDateFormat formater = new SimpleDateFormat("MMddHHmmyy");
        Date indentifier = formater.parse(date);
        Date newDate = new Date(indentifier.getTime() + add);
        return formater.format(newDate);
    }

    /**
     * 用于判断本条数据值是否重复
     * @param key：ip和设备名称组成
     * @return
     */
    private boolean isRepeat(String key) {
        long currentTime = Calendar.getInstance().getTimeInMillis();
        if (deviceMap.containsKey(key)) {
            long lastTime = deviceMap.get(key);
            if (currentTime - lastTime > cycleSecond) {//超过过滤周期
                deviceMap.put(key, currentTime);
                return false;
            }
            return true;
        }
        deviceMap.put(key, currentTime);
        return false;
    }

    @Override
    public String[] getParamMeta() {
        return new String[] { "cycle" };
    }

    @Override
    public String[] getPropMeta() {
        return new String[] { "IDENTIFIER", "TIMESTAMP", "ERROR_TYPE", "ERROR_CLASS", "RESOURCE_NAME", "DESCRIPTION", "ISREPEAT", "LABEL", "LOCATION" };
    }

    private String[] getDescriptionColumsZH() {
        return new String[] { "错误名称", "错误标示符", "发生时间", "事件编号", "序列号", "主机名", "错误类型", "错误级别", "资源名称", "资源类别", "资源类型", "部件位置" };
    }

    private String[] getDescriptionColumsEN() {
        return new String[] { "LABEL", "IDENTIFIER", "Date/Time", "Sequence Number", "Machine Id", "Node Id", "Class", "Type", "Resource Name", "Resource Class", "Resource Type", "Location" };
    }
}
